//****************************************************************
// File Name  : AR8035_cfg.v
// Author     : xianyong.chen
// Date       : 
// Description: 
//   It configures MII registers 
//****************************************************************
`timescale 1ns/1ns

module AR8035_cfg(
        input   wire            sclk,
        input   wire            clk_enable,
        input   wire            rst_n,

        output  reg     [4:0]   phy_addr,
        output  reg     [4:0]   reg_addr,
        output  reg             wr_en,
        output  reg     [15:0]  wr_data,
        input   wire            wr_end,
        output  reg             rd_en,
        input   wire            rd_data_vld,
        input   wire    [15:0]  rd_data
        );
//****************************************************************
reg     [2:0]   state;
localparam      IDLE            = 'd0;
localparam      PWR_ON_WAIT     = 'd1;
localparam      WR_REG          = 'd2;
localparam      JUDGE           = 'd3;
localparam      HALT            = 'd4;

reg     [19:0]  pwr_on_wait_cnt;
reg     [1:0]   wr_phy_cnt;
reg     [4:0]   wr_reg_cnt;

localparam      MAX_PWR_ON_WAIT_CNT     = 1000000; //10MHz -> 10ms
localparam      MAX_WR_PHY_CNT          = 2;
localparam      MAX_WR_REG_CNT          = 20;

localparam      PHY_ADDR_0              = 5'b00100;
localparam      PHY_ADDR_1              = 5'b00000;

localparam      REG_VAL_00              = 16'b0001_0001_0100_0000;
localparam      REG_VAL_1D              = 16'h0005;
localparam      REG_VAL_1E              = 16'h0100;

localparam      REG_00_ADDR             = 5'h0D;
localparam      REG_01_ADDR             = 5'h0E;
localparam      REG_02_ADDR             = 5'h0D;
localparam      REG_03_ADDR             = 5'h0E;
localparam      REG_04_ADDR             = 5'h0D;
localparam      REG_05_ADDR             = 5'h0E;
localparam      REG_06_ADDR             = 5'h0D;
localparam      REG_07_ADDR             = 5'h0E;
localparam      REG_08_ADDR             = 5'h0D;
localparam      REG_09_ADDR             = 5'h0E;
localparam      REG_10_ADDR             = 5'h0D;
localparam      REG_11_ADDR             = 5'h0E;
localparam      REG_12_ADDR             = 5'h1D;
localparam      REG_13_ADDR             = 5'h1E;
localparam      REG_14_ADDR             = 5'h1D;
localparam      REG_15_ADDR             = 5'h1E;

//localparam      REG_16_ADDR             = 5'h1D;  //
//localparam      REG_17_ADDR             = 5'h1E;  //
//localparam      REG_18_ADDR             = 5'h14;
//localparam      REG_19_ADDR             = 5'h00;
localparam      REG_18_ADDR             = 5'h1D;  //
localparam      REG_19_ADDR             = 5'h1E;  //
localparam      REG_16_ADDR             = 5'h14;
localparam      REG_17_ADDR             = 5'h00;

localparam      REG_00_VALUE            = 16'h0003;
localparam      REG_01_VALUE            = 16'h8003;
localparam      REG_02_VALUE            = 16'h4003;
localparam      REG_03_VALUE            = 16'hDD00;
localparam      REG_04_VALUE            = 16'h0003;
localparam      REG_05_VALUE            = 16'h8005;
localparam      REG_06_VALUE            = 16'h4003;
localparam      REG_07_VALUE            = 16'hCB32;
localparam      REG_08_VALUE            = 16'h0007;
localparam      REG_09_VALUE            = 16'h003C;
localparam      REG_10_VALUE            = 16'h4007;
localparam      REG_11_VALUE            = 16'h0000;
localparam      REG_12_VALUE            = 16'h000B;
localparam      REG_13_VALUE            = 16'h3C40;
localparam      REG_14_VALUE            = 16'h003D;
localparam      REG_15_VALUE            = 16'hE8E0;

//localparam      REG_16_VALUE            = 16'h0005; //
//localparam      REG_17_VALUE            = 16'h0100; //
//localparam      REG_18_VALUE            = 16'h000C;
//localparam      REG_19_VALUE            = 16'h9140;
localparam      REG_18_VALUE            = 16'h0005; //
localparam      REG_19_VALUE            = 16'h0000; //
localparam      REG_16_VALUE            = 16'h000C;
localparam      REG_17_VALUE            = 16'h9140;

localparam      AR8035_SELF_DELAY       = 0;
//****************************************************************
//state[2:0]
always@(posedge sclk or negedge rst_n)
    if(!rst_n)
        state <= IDLE;
    else if (clk_enable)
        case(state)
            IDLE:       state <= PWR_ON_WAIT;

            PWR_ON_WAIT:
                    if(pwr_on_wait_cnt==MAX_PWR_ON_WAIT_CNT-1)
                        state <= WR_REG;

            WR_REG:
                    if(wr_end==1)
                        state <= JUDGE;

            JUDGE:
                    if(wr_phy_cnt==MAX_WR_PHY_CNT-1 && wr_reg_cnt==MAX_WR_REG_CNT-1)
                        state <= HALT;
                    else
                        state <= WR_REG;

            HALT:       state <= HALT;

            default:    state <= IDLE;
        endcase
//****************************************************************
//pwr_on_wait_cnt[19:0]
always@(posedge sclk or negedge rst_n)
    if(!rst_n)
        pwr_on_wait_cnt <= 'b0;
    else if (clk_enable)
        begin
        if(state==PWR_ON_WAIT)
            pwr_on_wait_cnt <= pwr_on_wait_cnt + 1'b1;
        else
            pwr_on_wait_cnt <= 'b0;
        end

//wr_phy_cnt[1:0]
always@(posedge sclk or negedge rst_n)
    if(!rst_n)
        wr_phy_cnt <= 'b0;
    else if (clk_enable)
        begin
        if(state==IDLE)
            wr_phy_cnt <= 'b0;
        else if(state==JUDGE && wr_reg_cnt==MAX_WR_REG_CNT-1)
            wr_phy_cnt <= wr_phy_cnt + 1'b1;
        end

//wr_reg_cnt[4:0]
always@(posedge sclk or negedge rst_n)
    if(!rst_n)
        wr_reg_cnt <= 'b0;
    else if (clk_enable)
        begin
        if(state==IDLE)
            wr_reg_cnt <= 'b0;
        else if(state==JUDGE)
            begin
            if(wr_reg_cnt==MAX_WR_REG_CNT-1)
                wr_reg_cnt <= 'b0;
            else
                begin
                if(AR8035_SELF_DELAY==0 && wr_reg_cnt==15)
                    wr_reg_cnt <= wr_reg_cnt + 5'd3;
                else
                    wr_reg_cnt <= wr_reg_cnt + 1'b1;
                end
            end
        end
//****************************************************************
//phy_addr[4:0]
always@(posedge sclk)
    if (clk_enable)
        case(wr_phy_cnt)
            0:      phy_addr <= PHY_ADDR_0;
            1:      phy_addr <= PHY_ADDR_1;
        endcase

//wr_en
always@(posedge sclk or negedge rst_n)
    if(!rst_n)
        wr_en <= 'b0;
    else if (clk_enable)
        begin
        if(state==WR_REG)
            wr_en <= 1'b1;
        else
            wr_en <= 'b0;
        end

//reg_addr[4:0]
always@(posedge sclk)
    if (clk_enable)
        case(wr_reg_cnt)
            0 :      reg_addr <= REG_00_ADDR;
            1 :      reg_addr <= REG_01_ADDR;
            2 :      reg_addr <= REG_02_ADDR;
            3 :      reg_addr <= REG_03_ADDR;
            4 :      reg_addr <= REG_04_ADDR;
            5 :      reg_addr <= REG_05_ADDR;
            6 :      reg_addr <= REG_06_ADDR;
            7 :      reg_addr <= REG_07_ADDR;
            8 :      reg_addr <= REG_08_ADDR;
            9 :      reg_addr <= REG_09_ADDR;
            10:      reg_addr <= REG_10_ADDR;
            11:      reg_addr <= REG_11_ADDR;
            12:      reg_addr <= REG_12_ADDR;
            13:      reg_addr <= REG_13_ADDR;
            14:      reg_addr <= REG_14_ADDR;
            15:      reg_addr <= REG_15_ADDR;
            16:      reg_addr <= REG_16_ADDR;
            17:      reg_addr <= REG_17_ADDR;
            18:      reg_addr <= REG_18_ADDR;
            19:      reg_addr <= REG_19_ADDR;
        endcase

//wr_data[15:0]
always@(posedge sclk)
    if (clk_enable)
        case(wr_reg_cnt)
            0 :      wr_data <= REG_00_VALUE;
            1 :      wr_data <= REG_01_VALUE;
            2 :      wr_data <= REG_02_VALUE;
            3 :      wr_data <= REG_03_VALUE;
            4 :      wr_data <= REG_04_VALUE;
            5 :      wr_data <= REG_05_VALUE;
            6 :      wr_data <= REG_06_VALUE;
            7 :      wr_data <= REG_07_VALUE;
            8 :      wr_data <= REG_08_VALUE;
            9 :      wr_data <= REG_09_VALUE;
            10:      wr_data <= REG_10_VALUE;
            11:      wr_data <= REG_11_VALUE;
            12:      wr_data <= REG_12_VALUE;
            13:      wr_data <= REG_13_VALUE;
            14:      wr_data <= REG_14_VALUE;
            15:      wr_data <= REG_15_VALUE;
            16:      wr_data <= REG_16_VALUE;
            17:      wr_data <= REG_17_VALUE;
            18:      wr_data <= REG_18_VALUE;
            19:      wr_data <= REG_19_VALUE;
        endcase
//****************************************************************
endmodule
